<?php
  /** Une classe représentant les groupes utilisateurs
   * Auteur : Sebastian Mosser
   */
   
class User implements iPersistantData, iLookable , iHTMLViewable {

	private $_id;
	private $_login;
	private $_passwd;
	private $_groups;
	
	public function __construct($login,$id = -1) {
		$this->_login    = $login;
		$this->_id       = $id;
		$this->_groups   = array();
	}
	
	public function getLogin()    { return $this->_login;    }
	public function getGroups()   { return $this->_groups;   }
	public function getId()       { return $this->_id;       }

	public function addInGroup($groupId)   { $this->_groups[$groupId] = True;  }
	
	public function delFromGroup($groupId) { $this->_groups[$groupId] = False; }
	
	public function setPassword($passwd)   { $this->_passwd = sha1($passwd);   }
	
	public function setLogin($newLogin)    { $this->_login = $newLogin;        }

	public static function exists($login) {
		$myDb = Database::getSingleton();
		$login = Database::escape($login);
		$query = "SELECT * FROM `user` WHERE `login` = '$login';";
		$ans = Database::assoc($myDb->execute($query));
		return ($ans ? True : False);
	}


	// Pour savoir si des données sont potentiellement valides :
	public static function isValid($mylogin,$mypasswd,$mygroups, $oldLogin="") {
		$error = array();
		// Tests de validités effectués quoi qu'il arrive
		//   Sur le login a ajouter dans le système
		if ($mylogin == "")
   			$error["login"] = "Le nom de login ne peut pas être vide !!";
   		else if (strlen($mylogin) < 6)
   			$error["login"] = "Le nom de login est trop court (minimum 6 caractères) !!";
   		else if (strlen($mylogin) > 10)
   			$error["login"] = "Le nom de login est trop long (maximum 10 caractères) !!";
   		else if (strpos($mylogin," "))
   			$error["login"] = "Le nom de login ne doit pas contenir d'espace !";
   			
   		// Sur les groupes : 
   		if (empty($mygroups))
   			$error["groups"] = "L'utilisateur doit appartenir à au moins 1 groupe !";


		if ($oldLogin == "") {   		
			// Test de validité effectué a l'ajout d'un nouvel utilisateur
			if (self::exists($mylogin)) 
   				$error["login"] = "Un utilisateur ayant le nom de login [$mylogin] existe déja !";
   			if ($mypasswd == "")
   				$error["passwd"] = "Le mot de passe ne peut pas être vide !!";
   			if (strlen($mypasswd) < 6)
   				$error["passwd"] = "Le mot de passe est trop court (minimum 6 caractères) !!";
		}
		else {
			// Tests de validité effectués a la modification d'un utilisateur
			if ($oldLogin != $mylogin)
				if (self::exists($mylogin))
					$error["login"] = "Le nom de login [$mylogin] est déjà pris !";
			if ($mypasswd != "")
				if (strlen($mypasswd) < 6)
   					$error["passwd"] = "Le nouveau mot de passe est trop court (minimum 6 caractères) !!";
		}   		
   		
   		return $error;
	}


	/** Implementation de l'interface iPersistantData **/

	public static function createTable() {
		$myDb = Database::getSingleton();
		
		// Table de stockage persistante 
		$query  = "CREATE TABLE IF NOT EXISTS `user` (\n";
		$query .= "  `id`     INTEGER  NOT NULL PRIMARY KEY auto_increment, \n"; 
		$query .= "  `login`  VARCHAR(10) NOT NULL, \n ";
		$query .= "  `passwd` VARCHAR(40) NOT NULL \n); ";
		$myDb->execute($query);
		
		// Table de liaisons user/group
		$query  = "CREATE TABLE IF NOT EXISTS `user_group_lnk` (\n";
		$query .= "  `id`       INTEGER NOT NULL PRIMARY KEY auto_increment,\n";
		$query .= "  `user_id`  INTEGER NOT NULL REFERENCES `user`, \n";
		$query .= "  `group_id` INTEGER NOT NULL REFERENCES `group`); ";
		$myDb->execute($query);
		
		
	}
	
	public static function dropTable() {
		$myDb = Database::getSingleton();
		$query = "DROP TABLE IF EXISTS `user`;";
		$myDb->execute($query);
		$query = "DROP TABLE IF EXISTS `user_group_lnk`;";
		$myDb->execute($query);
	}
	
	public function create() {
		if ($this->_id != -1)
			throw new RuntimeException("User/create()", 
								"This object is still present in database !");
		$myDb = Database::getSingleton();
		
		// Creation dans la table persistante
		$login    = Database::escape($this->_login);
		$passwd   = Database::escape($this->_passwd);
		
		if (self::exists($login))
			throw new RuntimeException("User/create()",
								"This login name isn't available");
		
		$query  = "INSERT INTO `user` VALUES (\n";
		$query .= "  '', '$login', '$passwd'); ";
		/**
		$myDb->execute($query);
		($myDb->lastKeyValue() != 0 ? 
			$this->_id = $myDb->lastKeyValue() : 
			$this->_id = -1);
		**/
		$result = $myDb->executeInsert($query);
		if ($result[0] != 0)
			$this->_id = $result[0];
		else
			$this->id = -1;
		// Création des liaisons
		$this->manageLink();
		
	}
	
	public static function read($key) {
		$myDb = Database::getSingleton();
		
		// Recuperation de l'utilisateur
		$key = Database::escape($key);
		$query = "SELECT * FROM `user` WHERE `id` = $key;";
		$ans = Database::assoc($myDb->execute($query));
		if (! $ans)
			throw new RuntimeException("User/read()","Unknown '$key'");

		$aUser = new User($ans["login"], $ans["id"]);
		
		// Recuperation des groupes d'appartenances
		$query = "SELECT * FROM `user_group_lnk` WHERE `user_id` = ";
		$query .= $ans["id"] . ";" ;
		$result = $myDb->execute($query);
		while (($tuple = Database::assoc($result)) != False) {
			$aUser->addInGroup($tuple["group_id"]);
		}
		
		// Renvoie de l'instance appropriee :
		return $aUser;
	}

	public function update() {
		$myDb = Database::getSingleton();
		if ($this->_id == -1)
			throw new RuntimeException("User/create()",
												"This object isn't present in database !");
		$query  = "UPDATE `user` SET \n";
		$query .= "  `login` = '$this->_login', \n";
		$query .= "  `passwd` = '$this->_passwd' \n";
		$query .= "  WHERE `id` = $this->_id;";
		$myDb->execute($query);
		$this->manageLink();
	}
	
	// supression d'un element
	public function delete() {
		$myDb = Database::getSingleton();
		if ($this->_id == -1)
			throw new RuntimeException("User/delete()",
												"This object isn't present in database !");
		$query = "DELETE FROM `user` WHERE `id` = '$this->_id';";
		$myDb->execute($query);
		$query = "DELETE FROM `user_group_lnk` WHERE `user_id` = '$this->_id';";
		$myDb->execute($query);
	}
	
	private function manageLink() {
		$myDb = Database::getSingleton();
		foreach ($this->_groups as $key => $value) {
			// Test de la pré-éxistance en dbms :
			$query = "SELECT * FROM `user_group_lnk`WHERE `user_id` = '$this->_id' AND `group_id` = '$key';";
			$present  = Database::assoc($myDb->execute($query));
			// Maintenant, on peut travailler :
			if ($value == True ) {
				if ($present)
					continue; // Le lien est déjà présent
				$query = "INSERT INTO `user_group_lnk` VALUES ('','$this->_id','$key');";
				$myDb->execute($query);
			}
			else {
				if (! $present)
					continue; // Le lien n'est pas présent
				$query = "DELETE FROM `user_group_lnk` WHERE `user_id` = '$this->_id' AND `group_id` = '$key';";
				$myDb->execute($query);
			}
		}
	}

	public function tag() {
	 		$tmp = array();
	 		$tmp[0] = "User";
	 		$tmp[1] = $this->_id;
	 		return $tmp;
	}
	
	public function soundsLike($o) {
	  return ($this->_login == $o->_login);
	}
	 	
	/** Fin de l'implementation de l'interface iPersistantData **/
   
   public static function lookOnLogin($login) {
      $filter = Database::escape($login);
		$myDb   = Database::getSingleton();
		$query  = "SELECT * FROM `user` WHERE `login` = '$filter';";
		$ans    = $myDb->execute($query);
		return $ans;
   }

	/** Implementation de l'interface de recherche **/
	public static function lookFor($filter) {
		$filter = Database::escape($filter);
		$myDb   = Database::getSingleton();
		$query  = "SELECT * FROM `user` WHERE `login` LIKE '$filter' ORDER BY `login`;";
		$ans    = $myDb->execute($query);
		return $ans;
	}
	
	public static function showResult($resultSet,$scriptUrl = ""){ 
      $result  = "<div align=\"center\">\n";
      $result .= "  <table class=\"resultset\">\n";
      $result .= "    <tr><th>Utilisateur</th><th>Groupes d'appartenance</th></tr>\n";
      
	   while (($row = Database::assoc($resultSet)) != False) {
	      	$result .= "    <tr>". User::read($row["id"])->displayInline($scriptUrl)."</tr>\n";
	   }
	   
	   $result .= "  </table>\n</div>";
	   return $result;
	}
	
	/** Fin de l'implementation de iLookable **/

	/** Implementation de l'interface de vision HTML **/
	
	public function displayLong() {
		$result  = "<ul>\n";
		$result .= "<li> Login : <code>". $this->_login ."</code></li>\n";
		$i = 0; $tmp = "";
		foreach ($this->_groups as $key => $value) {
			$i++; $tmp .= "    <li>". Group::read($key)->displayShort()."</li>\n";
		}
		if ($i != 0) {
			$result .= "<li> Groupes d'appartenance : \n";
			$result .= "  <ul>\n";
			$result .= $tmp;
			$result .= "  </ul>\n";
		}
		$result .= "</ul>";
		return $result;
	}
	
	public function displayShort() {
		return $this->_login;
	}
	public function displayInline($scriptUrl="") {
	   $groups = "";
	   foreach ($this->_groups as $key => $value)
			$groups .= Group::read($key)->displayShort()." ";
			
		if ($groups == "")
			$groups = "Aucun Groupes ...";
		
		$ans = "";
		if ($scriptUrl == "")
   			$ans = "<td><code>$this->_login</code></td><td> $groups </td>";
   		else {
   		
   			$ans = "<td><code><a href=\"";
   			$ans .= $scriptUrl . "userId=" . $this->_id;
   			$ans .= "\">$this->_login</a></code></td><td> $groups </td>";
 		}
 		return $ans;
	}
	
	/** Fin de l'impelmentation d'iHTMLViewable **/

	/** Pour avoir les users sous forme de liste déroulante **/
	
	public static function getAsList($group, $selected = -1) {
		$group = Database::escape($group);
		$query  = "SELECT user.id AS id, user.login AS login FROM user_group_lnk,";
		$query .= " user WHERE group_id = $group AND user.id = user_id";
		$query .= " ORDER BY login ASC;";
		
		$myDb = Database::getSingleton();
		$ans = $myDb->execute($query);
		
		$content = "";
		while (($row = Database::assoc($ans)) != False) {
			$aUser = User::read($row["id"]);
			$s = (($selected == $aUser->_id) ? "selected" : "");
			$content .= "<option value=\"".$aUser->_id."\" ${s} >" . $aUser->_login;
			$content .= "</option>";
		}
	
		return $content;
	
	}
	
	
	public static function getAllAsList() {
		$sql = "SELECT * FROM `user` ORDER BY `login`";
		$myDb = Database::getSingleton();
		$ans = $myDb->execute($sql);
		
		$result = "";
		while (($row = Database::assoc($ans)) != False) {
			$result .= "<option value=\"" . $row["id"] . "\" > ";
			$result .= $row["login"] . "</option>\n";
		}
		return $result;
	}


}


?>